/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_httpd.htm
 *
 * Zhiqim Httpd is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.httpd.bio;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

import org.zhiqim.httpd.HttpListener;
import org.zhiqim.httpd.HttpServer;
import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.Closes;
import org.zhiqim.kernel.util.Sockets;
import org.zhiqim.kernel.util.Validates;

/**
 * HTTP阻塞式监听器 
 * 
 * @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
 */
public class HttpBioListener extends HttpListener
{
    private ServerSocket serverSocket;
    
    public HttpBioListener(HttpServer server)
    {
        super(server);
    }
    
    @Override /** 线程开启前 */
    protected boolean openBefore()
    {
        //监听参数和线程池
        super.openBefore();
        
        try
        {//监听端口和守护线程
            if (Validates.isEmpty(listenerIp))
                serverSocket = new ServerSocket(listenerPort);
            else
                serverSocket = new ServerSocket(listenerPort, 50, InetAddress.getByName(listenerIp));
            serverSocket.setReuseAddress(true);
            return true;
        }
        catch (Exception e)
        {
            log.error("初始化ServerSocket时异常", e);
            throw Asserts.exception(e);
        }
    }

    @Override /** 线程关闭后 */
    protected void closeAfter()
    {
        if (serverSocket != null)
        {//关闭监听
            Closes.closeIgnoreException(serverSocket);
            serverSocket = null;
        }
        
        //关闭父类的控制器/定时任务/连接列表
        super.closeAfter();
    }

    @Override /** 线程持续运行 */
    protected void loop()
    {
        try
        {
            Socket socket = serverSocket.accept();
            Sockets.setOption(socket, true, soTimeoutMs, soLingerS, false);
            
            //连接交给控制器多线程处理
            controller.execute(add(newConnection(socket)));
        }
        catch (SocketException e)
        {
            if (!_SOCKET_CLOSED_.equalsIgnoreCase(e.getMessage()))
            {//非服务端自己关闭连接导致的异常打印
                log.error(toString() + "SocketException异常", e);
            }
        }
        catch (IOException e)
        {
            log.error(toString() + "IO异常", e);
        }
    }
    
    /** 新建连接 */
    private HttpBioConnection newConnection(Socket socket) throws IOException
    {
        return new HttpBioConnection(this, socket, socket.getInputStream(), socket.getOutputStream());
    }
}
